package main

import (
	"encoding/json"
	"fmt"
	"gin_learn/gin_tools"
	"github.com/gin-gonic/gin"
	"github.com/gin-gonic/gin/binding"
	"github.com/go-playground/validator/v10"
	"net/http"
	"time"
)

type Person struct {
	// json -> json请求体  form -> form表单，查询串   binding -> 参数校验
	///与 binding:"规则1，规则2"
	///或 binding:"规则1 |规则2"
	Age     uint8  `json:"age" form:"age" binding:"required,gt=10"` //gt必须使用数字
	Name    string `json:"name" form:"name" binding:"required"`
	Address string `json:"address" form:"address" binding:"required"`
}

type address struct {
	Street     string      `json:"street"`
	Ste        string      `json:"suite,omitempty"`
	City       string      `json:"city"`
	State      string      `json:"state"`
	Zipcode    string      `json:"zipcode"`
	Coordinate *coordinate `json:"coordinate,omitempty"`
}

type coordinate struct {
	Lat *float64 `json:"latitude,omitempty"`
	Lng *float64 `json:"longitude,omitempty"`
}

type booking struct {
	CheckIn  time.Time `form:"check_in" binding:"required,bookabledate" time_format:"2006-01-02" `
	CheckOut time.Time `form:"check_out" binding:"required,gtfield=CheckIn" time_format:"2006-01-02" `
}

func main() {
	r := gin.Default()
	if v, ok := binding.Validator.Engine().(*validator.Validate); ok {
		_ = v.RegisterValidation("bookabledate", bookableDate)
	}
	r.GET("/bind", func(c *gin.Context) {
		var p Person

		if err := c.ShouldBind(&p); err != nil {
			//c.String(500,"error occur! %v",err.Error())
			c.JSON(http.StatusOK, gin.H{"msg": err.Error()})
			c.Abort()
			return
		}
		//对象转json常用方法，也可使用gin.H{"":""}手动封装字段
		bytes, _ := json.Marshal(p)
		c.String(200, "%v", string(bytes))
	})

	//Golang 的 “omitempty” 关键字略解 https://www.jianshu.com/p/a2ed0d23d1b0
	r.GET("empty", func(app *gin.Context) {
		cData := `{
        "latitude": 0.0,
        "longitude": 0.0
    }`
		c := new(coordinate)
		_ = json.Unmarshal([]byte(cData), &c)

		// 具体处理逻辑...

		coordinateBytes, _ := json.MarshalIndent(c, "", "    ")
		fmt.Printf("%s\n", string(coordinateBytes))
	})

	//夸字段校验
	r.GET("booking", func(c *gin.Context) {
		var b booking
		//这里不加& 会有反射错误
		if err := c.ShouldBind(&b); err != nil {
			//c.JSON(500, gin.H{"error": err.Error()})
			fmt.Printf("字段校验查出错误：\n%v\n", err.Error())
			res := gin_tools.Result{}.ErrorRes(err.Error())
			c.JSON(500, res)
			return
		}
		c.JSON(200, gin.H{"msg": "success", "data": b})
	})
	_ = r.Run()
}
func bookableDate(fl validator.FieldLevel) bool {

	if date, ok := fl.Field().Interface().(time.Time); ok {
		today := time.Now()
		return date.After(today)
	}

	return false
}
